use std::{fs, io::{prelude::*, BufReader}, net::{TcpListener, TcpStream}};


// 单线程版本
fn main() {
    println!("Hello, keke");

    let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
    for stream in listener.incoming() {
        let stream = stream.unwrap();

        handle_connection(stream);
    }
}

// Rust 中的 :: 符号用于访问模块中的类型或函数。在 BufReader::new(&mut stream) 语句中，:: 符号用于访问 BufReader 模块中的 new 函数。
// unwrap() 方法用于从 Option 类型中获取值。如果 Option 类型的值为 None，则 unwrap() 方法会引发 panic
fn handle_connection(mut stream: TcpStream) {
    let buf_reader = BufReader::new(&mut stream);
    let request_line = buf_reader.lines().next().unwrap().unwrap();

    let (status_line, filename) = if request_line == "GET / HTTP/1.1" {
        ("HTTP/1.1 200 OK", "sill.html")
    } else {
        ("HTTP/1.1 404 NOT FOUND", "404.html")
    };

    let contents = fs::read_to_string(filename).unwrap();
    let length = contents.len();

    let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");

    stream.write_all(response.as_bytes()).unwrap();
}

/*

这个语句的作用是将 response 变量表示的 HTTP 响应数据发送给客户端。

stream 是一个 TcpStream 类型的对象，它可以向客户端发送数据。write_all() 方法用于向流中写入数据。as_bytes() 方法用于将 response 变量表示的字符串转换为字节数组。

因此，stream.write_all(response.as_bytes()).unwrap(); 语句的作用是：

将 response 变量表示的字符串转换为字节数组。
将字节数组写入 stream 流中。
在本例中，response 变量将保存 HTTP 响应数据。该响应数据将包含 HTTP 状态码、响应头和响应正文。

如果 write_all() 方法失败，则会引发 panic。
*/

/*
unwrap() 方法用于从 Option 类型中获取值，如果 Option 类型的值为 None，则 unwrap() 方法会引发 panic。

因此，stream.write_all(response.as_bytes()).unwrap(); 语句中的 unwrap() 方法的作用是检查 write_all() 方法的返回值是否为 Ok()。如果 write_all() 方法返回的值为 Err()，则 unwrap() 方法会引发 panic。

在本例中，如果 write_all() 方法失败，则表示无法将 HTTP 响应数据发送给客户端。这种情况下，程序应该引发 panic，以便用户能够了解错误并采取相应的措施。

如果您不想引发 panic，可以使用 expect() 方法来替代 unwrap() 方法。expect() 方法与 unwrap() 方法类似，但它允许您提供一个错误消息。如果 Option 类型的值为 None，则 expect() 方法会引发 panic，并将错误消息作为 panic 信息的一部分。

以下是使用 expect() 方法的示例：

Rust
let response = ...;
let bytes = response.as_bytes();

stream.write_all(bytes).expect("Failed to write HTTP response");
*/


fn main1() {
    let mut s = String::from("keke")

    change(&mut s);
}

fn change(m: &mut String) {
    m.push_str(", great");
}

